#include <func.h>

#define MAX_MAP_SIZE 4096 * 10
int main(int argc, char* argv[])
{
    if(argc != 3)
        error(1, 0, "Usage: %s src dst", argv[0]);

    int src_fd = open(argv[1], O_RDONLY);
    if(src_fd == -1)
        error(1, errno, "open %s failed", argv[1]);
    int dst_fd = open(argv[2], O_RDWR | O_CREAT| O_TRUNC, 0666);
    if(dst_fd == -1)
        error(1, errno, "open %s failed", argv[2]);

    struct stat statbuf;
    if(fstat(src_fd, &statbuf) == -1)
        error(1, errno, "fstat");
    if(ftruncate(dst_fd, statbuf.st_size) == -1)
        error(1, errno, "ftruncate");

    if(statbuf.st_size / 512 > statbuf.st_blocks)
    {
        //int page = (int)ceil(statbuf.st_size / 4096.0);
        while(lseek(dst_fd, 0, SEEK_CUR) < statbuf.st_size)
        {

            char buffer[4096];
            int count = read(src_fd, buffer, 4096);

            int i = 0;
            for(; i < count; ++i)
            {
                if(buffer[i] != '\0')
                    break;
            }
            if(i == count)
            {
                lseek(dst_fd, count, SEEK_CUR);
            }
            else if(i < count)
            {       
                //lseek(dst_fd, i, SEEK_CUR);
                if(write(dst_fd, buffer, count) == -1)
                    error(1, errno, "write");
            }
        }
    }
    else
    {
        //未完待续...
        off_t size = statbuf.st_size; // src文件的大小

        if(ftruncate(dst_fd, size) == -1)
            error(1, errno, "ftruncate");

        off_t start = 0;  // 偏移量
        off_t length = MAX_MAP_SIZE;

        while(start < size)
        {
            if(size - start < MAX_MAP_SIZE)
                length = size - start;
            void* src_m = mmap(NULL, length, PROT_READ, MAP_SHARED, src_fd, start);
            if(src_m == MAP_FAILED)
                error(1, errno, "mmap");
            void* dst_m = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, dst_fd, start);
            if(dst_m == MAP_FAILED)
                error(1, errno, "mmap");

            memcpy(dst_m, src_m, length);

            if(munmap(src_m, length) == -1)
                error(1, errno, "munmap");
            if(munmap(dst_m, length) == -1)
                error(1, errno, "munmap");
            start += length; 
        }
    }
    close(src_fd);
    close(dst_fd);
    return 0;
}

